package com.chenwc.netty.tcp;

import com.alibaba.fastjson.JSONObject;
import com.chenwc.netty.tcp.coder.Message;
import com.chenwc.netty.tcp.config.ChannelMap;
import com.chenwc.netty.tcp.config.NettyConfig;
import com.chenwc.netty.tcp.config.NettyProperties;
import com.chenwc.netty.tcp.enums.MessageEnum;
import com.chenwc.netty.tcp.task.KeepAliveTask;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;

public class Main {
	
	private static final Logger log = LoggerFactory.getLogger(Main.class);

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		
		NettyProperties nettyProperties = new NettyProperties();
		NettyConfig config = new NettyConfig(nettyProperties);
		ServerBootstrap serverBootstrap = config.serverBootstrap();
		NettyServerBoot nettyServerBoot = new NettyServerBoot(serverBootstrap, nettyProperties);
		try {
			nettyServerBoot.start();
		} catch (InterruptedException e) {
			// TODO 自动生成的 catch 块
            nettyServerBoot.close();
			e.printStackTrace();
		}
		
		KeepAliveTask keepAliveTask = new KeepAliveTask(() -> {
            // 刷新值
            try {
            	if (ChannelMap.getChannelHashMap() != null && ChannelMap.getChannelHashMap().size() > 0) {
                    for (Map.Entry<String, Channel> next : ChannelMap.getChannelHashMap().entrySet()) {
                        String key = next.getKey();
                        Channel channel = next.getValue();
                        //log.info("channel ID：【{}】", channel.id().asLongText());
                        //移除已中断的连接
                        if (!channel.isActive()) {
                            ChannelMap.getChannelHashMap().remove(key);
                            log.info("连接：{}， 已中断，移除出 ChannelMap", key);
                        }
                        //定时发送心跳包到客户端，心跳发送失败会结束所有进程并退出程序
                        //通过心跳机制，来互相确认是否在线
                        else {
                        	// 心跳消息
                        	JSONObject body = new JSONObject();
                        	body.put("Server", "Alive");
                        	body.put("Time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));
                        	Message message = new Message(body.toJSONString(), MessageEnum.CONNECT);
                            //log.info("回写心跳消息: " + message.toJsonString());
                            channel.writeAndFlush(message).addListener((ChannelFutureListener) future -> {
                                StringBuilder sb = new StringBuilder();
                                if (!StringUtils.isEmpty(key)) {
                                    sb.append("【").append(key).append("】");
                                }
                                if (future.isSuccess()) {
                                    log.info(sb + " 回写心跳消息成功: " + message.toJsonString());
                                } else {
                                    log.info(sb + " 回写心跳消息失败: " + message.toJsonString());
                                    ChannelMap.getChannelHashMap().remove(key);
                                    log.info("连接：{}， 回写心跳消息失败，移除出 ChannelMap", key);
                                }
                            });
						}
                    }
                }
            } catch (Exception e) {
                //Thread.currentThread().interrupt();
                e.printStackTrace();
            }
        }, 30, "监测 ChannelMap 中的连接是否中断");
        keepAliveTask.start();
	}

}
